package com.gesis.utils;

import java.io.File;
import java.io.IOException;

import java.io.FileInputStream;

import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Util class for JSF.
 * 
 * @author Sergey Aleksandrov
 */
@SuppressWarnings("deprecation")
public class FacesUtils {

	private static Map<String, String> entities;
	static {
		entities = new Hashtable<String, String>();
		entities.put("acute", "\u00B4");
		entities.put("quot", "\"");
		entities.put("amp", "\u0026");
		entities.put("lt", "\u003C");
		entities.put("gt", "\u003E");
		entities.put("nbsp", "\u00A0");
		entities.put("iexcl", "\u00A1");
		entities.put("cent", "\u00A2");
		entities.put("pound", "\u00A3");
		entities.put("curren", "\u00A4");
		entities.put("yen", "\u00A5");
		entities.put("brvbar", "\u00A6");
		entities.put("sect", "\u00A7");
		entities.put("uml", "\u00A8");
		entities.put("copy", "\u00A9");
		entities.put("ordf", "\u00AA");
		entities.put("laquo", "\u00AB");
		entities.put("not", "\u00AC");
		entities.put("shy", "\u00AD");
		entities.put("reg", "\u00AE");
		entities.put("macr", "\u00AF");
		entities.put("deg", "\u00B0");
		entities.put("plusmn", "\u00B1");
		entities.put("sup2", "\u00B2");
		entities.put("sup3", "\u00B3");
		entities.put("acute", "\u00B4");
		entities.put("micro", "\u00B5");
		entities.put("para", "\u00B6");
		entities.put("middot", "\u00B7");
		entities.put("cedil", "\u00B8");
		entities.put("sup1", "\u00B9");
		entities.put("ordm", "\u00BA");
		entities.put("raquo", "\u00BB");
		entities.put("frac14", "\u00BC");
		entities.put("frac12", "\u00BD");
		entities.put("frac34", "\u00BE");
		entities.put("iquest", "\u00BF");
		entities.put("Agrave", "\u00C0");
		entities.put("Aacute", "\u00C1");
		entities.put("Acirc", "\u00C2");
		entities.put("Atilde", "\u00C3");
		entities.put("Auml", "\u00C4");
		entities.put("Aring", "\u00C5");
		entities.put("AElig", "\u00C6");
		entities.put("Ccedil", "\u00C7");
		entities.put("Egrave", "\u00C8");
		entities.put("Eacute", "\u00C9");
		entities.put("Ecirc", "\u00CA");
		entities.put("Euml", "\u00CB");
		entities.put("Igrave", "\u00CC");
		entities.put("Iacute", "\u00CD");
		entities.put("Icirc", "\u00CE");
		entities.put("Iuml", "\u00CF");
		entities.put("ETH", "\u00D0");
		entities.put("Ntilde", "\u00D1");
		entities.put("Ograve", "\u00D2");
		entities.put("Oacute", "\u00D3");
		entities.put("Ocirc", "\u00D4");
		entities.put("Otilde", "\u00D5");
		entities.put("Ouml", "\u00D6");
		entities.put("times", "\u00D7");
		entities.put("Oslash", "\u00D8");
		entities.put("Ugrave", "\u00D9");
		entities.put("Uacute", "\u00DA");
		entities.put("Ucirc", "\u00DB");
		entities.put("Uuml", "\u00DC");
		entities.put("Yacute", "\u00DD");
		entities.put("THORN", "\u00DE");
		entities.put("szlig", "\u00DF");
		entities.put("agrave", "\u00E0");
		entities.put("aacute", "\u00E1");
		entities.put("acirc", "\u00E2");
		entities.put("atilde", "\u00E3");
		entities.put("auml", "\u00E4");
		entities.put("aring", "\u00E5");
		entities.put("aelig", "\u00E6");
		entities.put("ccedil", "\u00E7");
		entities.put("egrave", "\u00E8");
		entities.put("eacute", "\u00E9");
		entities.put("ecirc", "\u00EA");
		entities.put("euml", "\u00EB");
		entities.put("igrave", "\u00EC");
		entities.put("iacute", "\u00ED");
		entities.put("icirc", "\u00EE");
		entities.put("iuml", "\u00EF");
		entities.put("eth", "\u00F0");
		entities.put("ntilde", "\u00F1");
		entities.put("ograve", "\u00F2");
		entities.put("oacute", "\u00F3");
		entities.put("ocirc", "\u00F4");
		entities.put("otilde", "\u00F5");
		entities.put("ouml", "\u00F6");
		entities.put("divide", "\u00F7");
		entities.put("oslash", "\u00F8");
		entities.put("ugrave", "\u00F9");
		entities.put("uacute", "\u00FA");
		entities.put("ucirc", "\u00FB");
		entities.put("uuml", "\u00FC");
		entities.put("yacute", "\u00FD");
		entities.put("thorn", "\u00FE");
		entities.put("yuml", "\u00FF");
	}

	/**
	 * Get servlet context.
	 * 
	 * @return the servlet context
	 */
	public static ServletContext getServletContext() {
		return (ServletContext) FacesContext.getCurrentInstance()
				.getExternalContext().getContext();
	}

	/**
	 * Get managed bean based on the bean name.
	 * 
	 * @param beanName
	 *            the bean name
	 * @return the managed bean associated with the bean name
	 */
	public static Object getManagedBean(String beanName) {
		Object o = getValueBinding(getJsfEl(beanName)).getValue(
				FacesContext.getCurrentInstance());

		return o;
	}

	/**
	 * Remove the managed bean based on the bean name.
	 * 
	 * @param beanName
	 *            the bean name of the managed bean to be removed
	 */
	public static void resetManagedBean(String beanName) {
		getValueBinding(getJsfEl(beanName)).setValue(
				FacesContext.getCurrentInstance(), null);
	}

	/**
	 * Store the managed bean inside the session scope.
	 * 
	 * @param beanName
	 *            the name of the managed bean to be stored
	 * @param managedBean
	 *            the managed bean to be stored
	 */
	public static void setManagedBeanInSession(String beanName,
			Object managedBean) {
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
				.put(beanName, managedBean);
	}

	/**
	 * Get parameter value from request scope.
	 * 
	 * @param name
	 *            the name of the parameter
	 * @return the parameter value
	 */
	public static String getRequestParameter(String name) {
		return (String) FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get(name);
	}

	/**
	 * Add information message.
	 * 
	 * @param msg
	 *            the information message
	 */
	public static void addInfoMessage(String msg) {
		addInfoMessage(null, msg);
	}

	/**
	 * Add information message to a sepcific client.
	 * 
	 * @param clientId
	 *            the client id
	 * @param msg
	 *            the information message
	 */
	public static void addInfoMessage(String clientId, String msg) {
		FacesContext.getCurrentInstance().addMessage(clientId,
				new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
	}

	/**
	 * Add error message.
	 * 
	 * @param msg
	 *            the error message
	 */
	public static void addErrorMessage(String msg) {
		addErrorMessage(null, msg);
	}

	/**
	 * Add error message to a sepcific client.
	 * 
	 * @param clientId
	 *            the client id
	 * @param msg
	 *            the error message
	 */
	public static void addErrorMessage(String clientId, String msg) {
		FacesContext.getCurrentInstance().addMessage(clientId,
				new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
	}

	/**
	 * Evaluate the integer value of a JSF expression.
	 * 
	 * @param el
	 *            the JSF expression
	 * @return the integer value associated with the JSF expression
	 */
	public static Integer evalInt(String el) {
		if (el == null) {
			return null;
		}

		if (UIComponentTag.isValueReference(el)) {
			Object value = getElValue(el);

			if (value == null) {
				return null;
			} else if (value instanceof Integer) {
				return (Integer) value;
			} else {
				return new Integer(value.toString());
			}
		} else {
			return new Integer(el);
		}
	}

	private static Application getApplication() {
		ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder
				.getFactory(FactoryFinder.APPLICATION_FACTORY);
		return appFactory.getApplication();
	}

	private static ValueBinding getValueBinding(String el) {
		return getApplication().createValueBinding(el);
	}

	public static HttpServletRequest getServletRequest() {
		System.out.println(FacesContext.getCurrentInstance());

		return (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
	}

	private static Object getElValue(String el) {
		return getValueBinding(el).getValue(FacesContext.getCurrentInstance());
	}

	private static String getJsfEl(String value) {
		return "#{" + value + "}";
	}

	public static String getUrlActual() {
		return getServletRequest().getRequestURI();
	}

	public static String getDireccionRemota() {
		return getServletRequest().getRemoteAddr();
	}

	/**
	 * Convenience method to get the application's URL based on request
	 * variables.
	 */
	public static String getUrlAplicacion() {
		HttpServletRequest peticion = getServletRequest();
		return getUrlAplicacion(peticion);
		/*
		 * 
		 * StringBuffer url = new StringBuffer(); int port =
		 * peticion.getServerPort(); if (port < 0) { port = 80; // Work around
		 * java.net.URL bug } String scheme = peticion.getScheme();
		 * url.append(scheme); url.append("://");
		 * url.append(peticion.getServerName()); if ((scheme.equals("http") &&
		 * (port != 80)) || (scheme.equals("https") && (port != 443))) {
		 * url.append(':'); url.append(port); }
		 * url.append(peticion.getContextPath()); return url.toString();
		 */
	}

	/**
	 * Convenience method to get the application's URL based on request
	 * variables.
	 */
	public static String getUrlAplicacion(HttpServletRequest poPeticion) {

		StringBuffer url = new StringBuffer();
		int port = poPeticion.getServerPort();
		if (port < 0) {
			port = 80; // Work around java.net.URL bug
		}
		String scheme = poPeticion.getScheme();
		url.append(scheme);
		url.append("://");
		url.append(poPeticion.getServerName());
		if ((scheme.equals("http") && (port != 80))
				|| (scheme.equals("https") && (port != 443))) {
			url.append(':');
			url.append(port);
		}
		url.append(poPeticion.getContextPath());
		System.out.println(url.toString());

		return url.toString();
	}

	public static void redirect(String url) //throws Exception
    {
        try {
            url =url.replaceAll("amp;", "");
            //FacesUtils.getHttpServletResponse().sendRedirect(url);
            FacesContext.getCurrentInstance().responseComplete();
            FacesContext.getCurrentInstance().getExternalContext().redirect(url);
            
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
	
	/**
	 * Este m�todo devuelve el Ip de la maquina del usuario
	 * 
	 * @since 5.0
	 * @author siscjmvalencia
	 * @return String Numero Ip
	 * @FechaCreacion 2008/10/02
	 */
	public static String getIpNumber() {
		return getServletRequest().getRemoteAddr();
	}

	public static HttpSession getHttpSession() {
		HttpSession vResp = getServletRequest().getSession(true);
		return vResp;
	}

	public static String getHost() {
		HttpServletRequest vRequest = getServletRequest();
		return vRequest.getLocalName();
	}

	public static String getRutaAplicacion() {
		String vsRuta = getServletContext().getRealPath(File.separator);
		if (vsRuta == null) {
			vsRuta = "/home/jmesias/info/";
		}
		return vsRuta + File.separator;
	}

	public static String getRutaAplicacionContac() {
		String vsRuta = getServletContext().getRealPath(File.separator);
		if (vsRuta == null) {
			vsRuta = "/home/jmesias/info/";
		}
		return vsRuta;
	}

	public static String getRutaConfig() throws Exception {
		String ruta = getRutaAplicacion() + "config" + File.separator;
		return ruta;
	}
	
	public static String getRutaTpl() throws Exception {
		String ruta = getRutaAplicacion() + "tpl" + File.separator;
		return ruta;
	}
	
	public static HttpServletResponse getHttpServletResponse() {
		return (HttpServletResponse) FacesContext.getCurrentInstance()
				.getExternalContext().getResponse();
	}

	public static boolean userRegistrado() {
		HttpSession session = getHttpSession();
		if (session.getAttribute("uid") != null) {
			return true;
		} else {
			return false;
		}
	}

	public static void setObjectInsession(String vsAtributo, Object objeto)
			throws Exception {
		getHttpSession().setAttribute(vsAtributo, objeto);
	}

	public static Object getObjectInsession(String vsAtributo) throws Exception {
		return getHttpSession().getAttribute(vsAtributo);
	}

	public static Properties getProperties() throws Exception {
		Properties conf = new Properties();
		File fileConf = new File(getRutaConfig() + "config.properties");
		FileInputStream fis = new FileInputStream(fileConf);
		conf.load(fis);
		fis.close();
		return conf;
	}

	public static void fijarRedirect(String vsUrl) {
		getHttpSession().setAttribute("redirect", vsUrl);
	}

	public static void fijarUrlRedirectLogin(String vsUrl) {
		getHttpSession().setAttribute("redirectLogin", vsUrl);
	}

	public static String getUrlRedirectLogin() {
		return (String) getHttpSession().getAttribute("redirectLogin");
	}

	public static void clearUrlRedirectLogin() {
		getHttpSession().removeAttribute("redirectLogin");
	}

	public static String getServerInfo() {
		return getServletContext().getServerInfo();
	}

	public static String escapeHTML(String s) {

		String nohtml = s.replaceAll("\\<.*?>", "");
		nohtml = decode(nohtml);
		return nohtml;

	}

	public static String decode(String str) {
		StringBuffer ostr = new StringBuffer();
		int i1 = 0;
		int i2 = 0;

		while (i2 < str.length()) {
			i1 = str.indexOf("&", i2);
			if (i1 == -1) {
				ostr.append(str.substring(i2, str.length()));
				break;
			}
			ostr.append(str.substring(i2, i1));
			i2 = str.indexOf(";", i1);
			if (i2 == -1) {
				ostr.append(str.substring(i1, str.length()));
				break;
			}

			String tok = str.substring(i1 + 1, i2);
			if (tok.charAt(0) == '#') {
				tok = tok.substring(1);
				try {
					int radix = 10;
					if (tok.trim().charAt(0) == 'x') {
						radix = 16;
						tok = tok.substring(1, tok.length());
					}
					ostr.append((char) Integer.parseInt(tok, radix));
				} catch (NumberFormatException exp) {
					ostr.append('?');
				}
			} else {
				tok = (String) entities.get(tok);
				if (tok != null)
					ostr.append(tok);
				else
					ostr.append('?');
			}
			i2++;
		}
		return ostr.toString();
	}

}